home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / ARTAbrot 1.21 / BrotCode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-08  |  8.4 KB  |  334 lines  |  [TEXT/MPS ]

  1. /************************************************************************/
  2. /*                                                                        */
  3. /*    FILE:        BrotCode.c -- Code for computing Mandelbrots.            */
  4. /*                                                                        */
  5. /*    PURPOSE:    Code to communicate with DSP to calculate Mandelbrots.    */
  6. /*                                                                        */
  7. /*    AUTHOR:        George T. Warner                                        */
  8. /*                                                                        */
  9. /*    REVISIONS:                                                            */
  10. /*    03/26/94    Minor cleaning up.                                        */
  11. /*    08/22/93    First version.                                            */
  12. /*                                                                        */
  13. /************************************************************************/
  14.  
  15. #include <Quickdraw.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "DSPManager.h"
  20. #include "DSPConstants.h"
  21. #include "BrotCode.h"
  22. #include "ComUtil_ARTAbrot.h"    /* Common */
  23. #include "AB_Alert.h"
  24.  
  25. struct DSPCPUDeviceParamBlk pb, *pbPtr;
  26. DSPTaskRefNum taskRefNum;
  27. DSPModuleRefNum modRefNum;
  28. DSPSectionRefNum BroBufRefNum;
  29.  
  30. /* Offscreen pixMap stuff. */
  31. extern GWorldPtr offscreenGWorld;    /* Off screen graphics world. */
  32. extern Rect    GWorldBounds;            /* Boundaries of graphics world. */
  33.  
  34. int processing_brot = false;
  35. short *data_mem = nil;    /* Array for uploading Mandelbrot data into. */
  36. unsigned long ypoint;    /* Current y being processed. */
  37. int xpix, ypix;
  38. float fxdelta, fydelta;
  39. double distance_per_pixel, fheight;
  40.  
  41. #define NumElements 128L
  42.  
  43. typedef struct
  44. {
  45.     long Startflag;
  46.     long Doneflag;
  47.     long Points;
  48.     long Maxiter;
  49.     float Xstart;
  50.     float Delta;
  51.     float Ystart;
  52.     long Inited;
  53.     short OutputData[640];
  54. }
  55. MyPBuff;
  56.  
  57. MyPBuff *mypbuffptr;
  58.  
  59.  
  60. pascal void fatalError(DSPMessagePtr errorBlockPtr)
  61. {
  62. #pragma unused (errorBlockPtr)
  63. char tmp_string[256];
  64.  
  65.     sprintf(tmp_string, "MessageActionProc called.");
  66.     AB_Alert(tmp_string);
  67. }
  68.  
  69. void start_brot()
  70. {
  71. char tmp_string[256];
  72. OSErr err;
  73.     
  74.     SetPort(WPtr_ARTAbrot);
  75.  
  76.     /* Get width of image to calculate. */
  77.     xpix = (WPtr_ARTAbrot->portRect.right-WPtr_ARTAbrot->portRect.left)-SCROLLBARWIDTH;
  78.     /* Get height of image to calculate. */
  79.     ypix = (WPtr_ARTAbrot->portRect.bottom-WPtr_ARTAbrot->portRect.top)-SCROLLBARWIDTH;
  80.     /* Find the distance between pixels. */
  81.     distance_per_pixel = fwidth/(double)xpix;
  82.     /* Find the height of the image. */
  83.     fheight = (double)ypix * distance_per_pixel;
  84.  
  85.     pb.pbhDeviceIndex        = 0;                    /* Just use device 0. */
  86.     pb.pbhClientPermission    = kdspReadPermission;    /* Not sure what this means. */
  87.     pb.pbhDeviceICON        = nil;                    /* No icon desired. */
  88.     pb.pbhClientICON         = nil;
  89.     pb.cpuClientMessageActionProc = fatalError;
  90.     BlockMove("\pARTAbrot", pb.pbhClientName, 32);
  91.     
  92.     pbPtr = &pb;
  93.     
  94.     /* Get information on DSP 0. */
  95.     if (DSPGetIndexedCPUDevice(pbPtr)) {
  96.         sprintf(tmp_string, "Failure: No DSPs attached!");
  97.         AB_Alert(tmp_string);
  98.         return;
  99.     }
  100.  
  101.     /* Open device driver. */
  102.     if (DSPOpenCPUDevice(pbPtr)) {
  103.         sprintf(tmp_string, "Failure opening DSP device driver.");
  104.         AB_Alert(tmp_string);
  105.         return;
  106.     }
  107.     
  108.     /* Create a new task structure. */
  109.     if (DSPNewTask(pbPtr, &fatalError, "\pMandelbrot", &taskRefNum)) {
  110.         sprintf(tmp_string, "Failure creating new task structure.");
  111.         AB_Alert(tmp_string);
  112.         goto close_device;
  113.     }
  114.  
  115.     /* Load a module into the task structure. */
  116.     err = DSPLoadModule("\pmbrot",     /* Load MBrot resource. */
  117.                     taskRefNum,     /* Pass task structure reference number. */
  118.                     kdspAnyPositionInsert, /* Put it anywhere. */
  119.                     (DSPModuleRefNum)NULL,     /* Optional reference module number. */
  120.                     &modRefNum,     /* Pointer to get module reference number. */
  121.                     NumElements);    /* Scale multiplier (not sure about this yet). */
  122.     if (err) {
  123.         sprintf(tmp_string, "Failure loading MBrot module.");
  124.         AB_Alert(tmp_string);
  125.         goto dispose_task;
  126.     }
  127.  
  128.     /* Insert Task into Task List */
  129.     if (DSPInsertTask(pbPtr, taskRefNum, kdspAnyPositionInsert, kdspTimeShare, (DSPTaskRefNum)NULL)) {
  130.         sprintf(tmp_string, "Failure inserting task.");
  131.         AB_Alert(tmp_string);
  132.         goto dispose_task;
  133.     }
  134.  
  135.     /* Get section reference numbers for the parameter buffer. */
  136.     if (DSPGetSection(modRefNum,"\pbrobuf",&BroBufRefNum)) {
  137.         sprintf(tmp_string, "Failure getting parameter buffer reference number.");
  138.         AB_Alert(tmp_string);
  139.         goto remove_task;
  140.     }
  141.  
  142.     /* Get pointer to parameter buffer. */
  143.     err = DSPGetSectionData(BroBufRefNum,(Ptr *)&mypbuffptr);
  144.     if (err) {
  145.         sprintf(tmp_string, "Failure getting parameter buffer pointer.");
  146.         AB_Alert(tmp_string);
  147.         goto remove_task;
  148.     }
  149.  
  150.     /* Allocate buffer to hold one line of data. */
  151.     data_mem = (short *)calloc(xpix, sizeof(short));
  152.     if(!data_mem) {
  153.         sprintf(tmp_string, "Failure allocating data buffer.");
  154.         AB_Alert(tmp_string);
  155.         goto remove_task;
  156.     }
  157.  
  158.     fydelta = fxdelta = fwidth/xpix;
  159.     /* Download left coordinate of image. */
  160.     mypbuffptr->Xstart = fxcenter-(fwidth/2);
  161.     mypbuffptr->Delta = fxdelta;
  162.     /* Download bottom coordinate of image. */
  163.     mypbuffptr->Ystart = fycenter-(fheight/2);
  164.     /* Tell num. of pixels to do. */
  165.     mypbuffptr->Points = xpix;
  166.     mypbuffptr->Maxiter = fiters;
  167.     /* Start with first line. */
  168.     mypbuffptr->Doneflag = 0;
  169.     mypbuffptr->Startflag = 0;
  170.  
  171.     /* Start calculations! */
  172.     if (DSPSetTaskActive(taskRefNum)) {
  173.         sprintf(tmp_string, "Failure setting task active.");
  174.         AB_Alert(tmp_string);
  175.         goto quit_task;
  176.     }
  177.  
  178.     /* Wait for DSP module to initialize. */
  179.     while (!mypbuffptr->Inited) {
  180.         /* Force stop waiting if user hits command-period. */
  181.         if (check_stop()) {
  182.             goto inactivate_task;
  183.         }
  184.     }
  185.  
  186.     /* Start processing first line. */
  187.     mypbuffptr->Startflag = 1;
  188.     ypoint = 0;
  189.     processing_brot = true;
  190.  
  191.     return;
  192.  
  193. inactivate_task:
  194.     /* Inactivate task. */
  195.     if (DSPSetTaskInactive(taskRefNum)) {
  196.         sprintf(tmp_string, "Failure setting task inactive.");
  197.         AB_Alert(tmp_string);
  198.     }
  199.  
  200. quit_task:
  201.     if (data_mem)
  202.         free(data_mem);
  203.  
  204. remove_task:
  205.     /* Remove the Task */
  206.     if (DSPRemoveTask(taskRefNum)) {
  207.         ShowCursor();
  208.         sprintf(tmp_string, "Failure removing task.");
  209.         AB_Alert(tmp_string);
  210.     }
  211.  
  212. dispose_task:
  213.     /* Dispose the Task */
  214.     if (DSPDisposeTask(taskRefNum)) {
  215.         ShowCursor();
  216.         sprintf(tmp_string, "Failure disposing task.");
  217.         AB_Alert(tmp_string);
  218.     }
  219.  
  220. close_device:
  221.     /* Close the CPU Device */
  222.     if (DSPCloseCPUDevice(pbPtr)) {
  223.         ShowCursor();
  224.         sprintf(tmp_string, "Failure closing DSP driver.");
  225.         AB_Alert(tmp_string);
  226.     }
  227.  
  228.     new_coordinates=FALSE;
  229.     ShowCursor();
  230. }
  231.  
  232. void continue_brot()
  233. {
  234. Ptr base_addr;
  235. long row_bytes;    /* Used for PixMap calculations. */
  236. Rect rect_to_copy;
  237. unsigned char *pixel_address;
  238. long xpoint;
  239.     
  240.     if (!mypbuffptr->Doneflag) {
  241.         /* If no data to process, just return. */
  242.         return;
  243.     }
  244.  
  245.     SetPort(WPtr_ARTAbrot);
  246.  
  247.     /* Lock the offscreen GWorld. */
  248.     LockPixels(offscreenGWorld->portPixMap);
  249.     row_bytes = ((**(offscreenGWorld->portPixMap)).rowBytes) & 0x3fff;
  250.     base_addr = GetPixBaseAddr(offscreenGWorld->portPixMap);
  251.  
  252.     /* Copy data from DSP buffer. */
  253.     BlockMove(mypbuffptr->OutputData, data_mem, xpix * sizeof(short));
  254.  
  255.     ypoint++;
  256.  
  257.     if (ypoint != ypix) { /* Don't start new line if we don't need it. */
  258.         /* Download new Y coordinate. */
  259.         mypbuffptr->Ystart = (fycenter-(fheight/2)) + (ypoint * fxdelta);
  260.         /* Acknowledge that last line was completed. */
  261.         mypbuffptr->Doneflag = 0;
  262.         /* Tell it to go. */
  263.         mypbuffptr->Startflag = 1;
  264.     }
  265.  
  266.     /* Convert results to bytes for indexed color display. */
  267.     pixel_address = (unsigned char *)((unsigned long)base_addr + ((ypoint-1) * (unsigned long)row_bytes));
  268.     for (xpoint=0; xpoint < xpix; xpoint++)
  269.         *pixel_address++ = data_mem[xpoint];
  270.  
  271.     SetRect(&rect_to_copy, GWorldBounds.left, GWorldBounds.top+ypoint-1, GWorldBounds.right, GWorldBounds.top+ypoint); /* left, top, right, bottom */
  272.  
  273.     /* Display line on screen. */
  274.     CopyBits((BitMap *)*offscreenGWorld->portPixMap, &(WPtr_ARTAbrot->portBits), &(rect_to_copy), &(rect_to_copy), srcCopy, 0);
  275.  
  276.     UnlockPixels(offscreenGWorld->portPixMap);
  277.  
  278.     if (ypoint == ypix) {
  279.         /* If we are done, clean up. */
  280.         finish_brot();
  281.     }
  282. }
  283.  
  284.  
  285. void finish_brot()
  286. {
  287. char tmp_string[256];
  288.  
  289.     processing_brot = false;
  290.     
  291.     while (!mypbuffptr->Doneflag) {
  292.         /* Wait for last line to complete. */
  293.         if (check_stop()) {
  294.             /* If we can't wait or are hung, just get out. */
  295.             break;
  296.         }
  297.     }
  298.  
  299.     /* Inactivate task. */
  300.     if (DSPSetTaskInactive(taskRefNum)) {
  301.         sprintf(tmp_string, "Failure setting task inactive.");
  302.         AB_Alert(tmp_string);
  303.     }
  304.  
  305.     if (data_mem)
  306.         free(data_mem);
  307.  
  308.     /* Remove the Task */
  309.     if (DSPRemoveTask(taskRefNum)) {
  310.         ShowCursor();
  311.         sprintf(tmp_string, "Failure removing task.");
  312.         AB_Alert(tmp_string);
  313.     }
  314.  
  315.     /* Dispose the Task */
  316.     if (DSPDisposeTask(taskRefNum)) {
  317.         ShowCursor();
  318.         sprintf(tmp_string, "Failure disposing task.");
  319.         AB_Alert(tmp_string);
  320.     }
  321.  
  322.     /* Close the CPU Device */
  323.     if (DSPCloseCPUDevice(pbPtr)) {
  324.         ShowCursor();
  325.         sprintf(tmp_string, "Failure closing DSP driver.");
  326.         AB_Alert(tmp_string);
  327.     }
  328.  
  329.     new_coordinates=FALSE;
  330. }
  331.  
  332.  
  333.  
  334.